package com.zmn.brs.admin.controller.record;


import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.site.lookup.util.StringUtils;
import com.zmn.brs.business.interfaces.record.OperateRecordBService;
import com.zmn.brs.common.constant.BrsConst;
import com.zmn.brs.common.enums.EventEnum;
import com.zmn.brs.common.enums.EventTypeEnum;
import com.zmn.brs.common.enums.SceneTypeEnum;
import com.zmn.brs.common.util.ObjectConvertUtil;
import com.zmn.brs.model.entity.event.EventBase;
import com.zmn.brs.model.entity.record.EventRecord;
import com.zmn.brs.model.entity.record.EventRecordQuery;
import com.zmn.brs.model.query.record.ObjectQuery;
import com.zmn.brs.model.vo.record.EventRecordVO;
import com.zmn.brs.services.interfaces.event.EventService;
import com.zmn.brs.services.interfaces.record.EventRecordService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto.VtDTO;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.logger.LoggerUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.office.ExcelUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.mcc.cas.web.StaffAdminService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 触发事件基础查询Controller
 *
 * @author xujie
 * @since 2021-03-17 13:55:07
 * @modi
 */
@Slf4j
@RestController
@RequestMapping("/brs/record/")
public class EventRecordListController {

    @Resource
    private OperateRecordBService operateRecordBService;

    @Resource
    private EventRecordService eventRecordService;

    @Resource
    private EventService eventService;

    /**
     * 列表
     *
     * @author xujie
     * @since 2021-03-18 17:55:07
     * @modifier zhangyao 2021-4-24
     */
    @RequestMapping("/list")
    @RequiresPermissions("/brs/record/list.action")
    public ModelAndView list(@ModelAttribute EventRecordQuery query, HttpServletRequest req) {

        Map<String, String[]> parameterMap = req.getParameterMap();
        Map<String, Object> expand = new HashMap<>();
        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            if(entry.getKey().startsWith("expand.")){
                String[] value = entry.getValue();
                if(value == null || value.length == 0){
                    continue;
                }
                expand.put(entry.getKey().replace("expand.", ""), value[0]);
            }
        }
        query.setExpand(expand);
        query.setSceneType(SceneTypeEnum.SENSITIVE.getTypeId());
        List<EventRecordVO> eventRecordVOList = getEventRecordVoList(query);
        List<VtDTO> typeList = Stream.of(EventTypeEnum.values())
                .map(item -> new VtDTO(item.getTypeId(),item.getTypeName(), item.getTypeId().equals(query.getEventType())))
                .collect(Collectors.toList());
        List<VtDTO> objectIdentityList = new ArrayList<>();
        Integer objectIdentity = Objects.nonNull(expand.get("objectIdentity")) && StringUtils.isNotEmpty(expand.get("objectIdentity").toString()) ? Integer.parseInt(expand.get("objectIdentity").toString()) : GlobalConsts.NONE;
        objectIdentityList.add(new VtDTO(GlobalConsts.OPERATE_USER_TYPE_STAFF, "员工", new Integer(GlobalConsts.OPERATE_USER_TYPE_STAFF).equals(objectIdentity)));
        objectIdentityList.add(new VtDTO(GlobalConsts.OPERATE_USER_TYPE_MASTER, "工程师", new Integer(GlobalConsts.OPERATE_USER_TYPE_MASTER).equals(objectIdentity)));
        objectIdentityList.add(new VtDTO(GlobalConsts.OPERATE_USER_TYPE_USER, "用户", new Integer(GlobalConsts.OPERATE_USER_TYPE_USER).equals(objectIdentity)));
        objectIdentityList.add(new VtDTO(GlobalConsts.OPERATE_USER_TYPE_FACTORY, "厂商", new Integer(GlobalConsts.OPERATE_USER_TYPE_FACTORY).equals(objectIdentity)));
        objectIdentityList.add(new VtDTO(GlobalConsts.OPERATE_USER_TYPE_SERVICEPROVIDER, "服务商", new Integer(GlobalConsts.OPERATE_USER_TYPE_SERVICEPROVIDER).equals(objectIdentity)));
        ModelAndView mav = new ModelAndView("record/list");
        boolean showExportExcel = StaffAdminService.isPermitted("/brs/record/export.action");
        mav.addObject("showExportExcel", showExportExcel);
        mav.addObject("typeList", typeList);
        mav.addObject("objectIdentityList", objectIdentityList);
        mav.addObject("items", eventRecordVOList);
        query.setExportLimit(StaffAdminService.currentStaff().getExportLimit());
        query.setObjectIdentity(objectIdentity);
        mav.addObject("vo", query);
        mav.addObject("dayLimit", 0 - Optional.ofNullable(StaffAdminService.currentStaff().getDayLimit()).orElse(0));
        return mav;
    }


    /**
     * 对象搜索
     *
     * @return List<VtDTO>
     * @author xujie
     * @since 2021-03-19 09:55:07
     * @modifier zhangyao 2021-04-23 增加工程师、厂商、服务商的搜索
     */
    @RequestMapping(value = "/search/object", method = RequestMethod.POST)
    public ResponseDTO<List<VtDTO>> searchObject(@RequestBody ObjectQuery query) {

        List<VtDTO> list = operateRecordBService.listObjectByQuery(query);

        return ResponseDTO.success(list);
    }

    /**
     * 描述: 检查当前员工是否配置了导出数量，没配置则不能导出
     *
     **/
    @RequestMapping(value = "/checkStaffExportTotalCount")
    public ResponseDTO<Boolean> checkStaffExportTotalCount() {

        if (NumberUtil.isNullOrZero(StaffAdminService.currentStaff().getExportLimit())) {
            return ResponseDTO.fail("您没有配置导出数量，无法导出");
        }
        return ResponseDTO.success();
    }

    /**
     * 描述: 导出监控记录
     *
     * @param query 查询条件
     * @author xujie
     * @since 2020/10/28
     **/
    @RequestMapping(value = "/exportRecordExcel")
    public void exportRecordExcel(HttpServletResponse response, EventRecordQuery query) {

        query.setPageIndex(1);
        query.setPageSize(StaffAdminService.currentStaff().getExportLimit());
        List<EventRecordVO> eventRecordVOList = getEventRecordVoList(query);
        List<List> lists = Lists.newArrayListWithExpectedSize(eventRecordVOList.size());
        String[] title = {"身份", "身份名称", "身份属性", "操作类型", "具体操作", "监控场景", "渠道名称", "备注", "时间"};
        lists.add(Arrays.asList(title));
        eventRecordVOList.forEach(e -> {
            List<Object> item = new ArrayList<>();
            item.add(e.getObjectIdentity());
            item.add(e.getRealName());
            item.add(e.getObjectIdentityAttribute());
            item.add(e.getOperationType());
            item.add(e.getOperation());
            item.add(e.getMonitorScene());
            item.add(e.getChannelName());
            item.add(e.getRemarks());
            item.add(e.getCreateTime());
            lists.add(item);
        });
        try {
            String excelName =  "安全监控.xlsx";
            String name = new String(excelName.getBytes(), StandardCharsets.ISO_8859_1);
            ExcelUtil.export(response, lists, name, "sheet");
        } catch (Exception e) {
            LoggerUtil.error(this.getClass(), "导出报表出错" + e.getMessage(), e);
        }

    }

    /**
     * 查询操作记录数据，并组装成VO列表
     * @param query 查询条件
     * @return java.util.List<com.zmn.brs.model.vo.record.EventRecordVO>
     * @throws
     * @author zhangyao
     * @since 2021/04/24 16:59
     */
    private List<EventRecordVO> getEventRecordVoList(EventRecordQuery query) {

        List<EventBase> eventBaseList = new ArrayList<>();
        if (StringUtil.isNotBlank(query.getObjectIds())) {
            List<Integer> staffIdList = Arrays.stream(query.getObjectIds().split(",")).map(Integer::parseInt).collect(Collectors.toList());
            query.setObjectIdList(staffIdList);
        }
        if (StringUtil.isNotBlank(query.getEngineerIds())) {
            List<Integer> engineerIdsList = Arrays.stream(query.getEngineerIds().split(",")).map(Integer::parseInt).collect(Collectors.toList());
            if (query.getObjectIdList() != null) {
                query.getObjectIdList().addAll(engineerIdsList);
            } else {
                query.setObjectIdList(engineerIdsList);
            }
        }
        if (query.getEventType() != null) {
            eventBaseList = eventService.listByEventType(query.getEventType());
            List<Integer> eventCodeList = eventBaseList.stream().map(EventBase::getEventCode).collect(Collectors.toList());
            query.setEventCodeList(eventCodeList);
        }
        if (StringUtil.isNotBlank(query.getTimeSearch())) {
            String[] timeRangeArray = query.getTimeSearch().split("-");
            query.setStartTime(timeRangeArray[0].trim() + " 00:00:00");
            query.setEndTime(timeRangeArray[1].trim() + " 23:59:59");
        }
        Integer dayLimit = StaffAdminService.currentStaff().getDayLimit();
        if (dayLimit != null && dayLimit == 0) {
            return new ArrayList<>();
        }
        if (dayLimit != null) {
            Date date = DateUtil.addDays(new Date(), -dayLimit);
            String startTime = query.getStartTime();
            if (startTime == null) {
                query.setStartTime(DateUtil.dateFormatToString(date, DateUtil.FORMAT_DEFAULT));
            } else {
                if (DateUtil.dateFormatToDate(startTime, DateUtil.FORMAT_DATE3 + " HH:mm:ss").before(date)) {
                    query.setStartTime(DateUtil.dateFormatToString(date, DateUtil.FORMAT_DEFAULT));
                }
            }
            if (query.getEndTime() == null) {
                query.setEndTime(DateUtil.dateFormatToString(new Date(), DateUtil.FORMAT_DEFAULT));
            }
        }
        query.setRealName(StringUtils.isEmpty(query.getRealName()) ? null : query.getRealName());
        List<EventRecord> items = eventRecordService.listPageByQuery(query);
        if (query.getEventType() == null) {
            List<Integer> eventCodeList = items.stream().map(EventRecord::getEventCode).collect(Collectors.toList());
            eventBaseList = eventService.listByEventCodeList(eventCodeList);
        }
        Map<Integer, EventBase> eventBaseMap = eventBaseList.stream().collect(Collectors.toMap(EventBase::getEventCode, e -> e));
        // 组装前台显示数据
        List<EventRecordVO> eventRecordVOList = new ArrayList<>(items.size());
        for (EventRecord e : items) {
            EventBase eventBase = Optional.ofNullable(eventBaseMap.get(e.getEventCode())).orElse(new EventBase());
            String typeName;
            EventTypeEnum eventTypeEnum = EventTypeEnum.getEventTypeEnum(eventBase.getEventType());
            if (eventTypeEnum == null) {
                typeName = "";
            } else {
                typeName = eventTypeEnum.getTypeName();
            }
            EventRecordVO recordVO = EventRecordVO.builder()
                    .recordId(e.getRecordId())
                    .objectId(e.getObjectId())
                    .objectName(e.getObjectName())
                    .realName(e.getRealName())
                    .operationType(typeName)
                    .operation(eventBase.getEventName())
                    .monitorScene(e.getMonitorScene())
                    .remarks(e.getRemarks())
                    .createTime(DateUtil.dateFormatToString(e.getCreateTime(), DateUtil.FORMAT_DEFAULT))
                    .build();
            String expand = e.getExpand();
            if(!org.springframework.util.StringUtils.isEmpty(expand)){
                JSONObject jsonObject = JSONObject.parseObject(expand);
                // 转换身份枚举值为对应的身份文字信息
                Integer objectIdentity = ObjectConvertUtil.toInteger(jsonObject.get("objectIdentity"), GlobalConsts.OPERATE_USER_TYPE_STAFF);
                String objectIdentityText = objectIdentity.equals(GlobalConsts.OPERATE_USER_TYPE_STAFF) ? "员工"
                        : objectIdentity.equals(GlobalConsts.OPERATE_USER_TYPE_MASTER) ? "工程师"
                        : objectIdentity.equals(GlobalConsts.OPERATE_USER_TYPE_USER) ? "用户"
                        : objectIdentity.equals(GlobalConsts.OPERATE_USER_TYPE_FACTORY) ? "厂商"
                        : objectIdentity.equals(GlobalConsts.OPERATE_USER_TYPE_SERVICEPROVIDER) ? "服务商" : "";
                // 根据对象身份属性显示对应属性的值
                Integer objectIdentityAttribute = ObjectConvertUtil.toInteger(jsonObject.get("objectIdentityAttribute"), BrsConst.OBJECT_IDENTITY_ATTRIBUTE_ID);
                String objectIdentityAttributeValue = ObjectConvertUtil.toString(jsonObject.get("objectIdentityAttributeValue"));
                String objectIp = Optional.ofNullable(jsonObject.get("objectIp")).orElse("").toString();
                String objectIdentityAttributeText;
                if ((e.getEventCode() < EventEnum.VALUE_ADDED_WORK_ORDER_PLACE_AN_ORDER.getEventCode()
                        && objectIdentity.equals(GlobalConsts.OPERATE_USER_TYPE_MASTER))
                        || objectIdentity.equals(GlobalConsts.OPERATE_USER_TYPE_STAFF)) {
                    objectIdentityAttributeText = e.getObjectName();
                } else {
                    objectIdentityAttributeText = objectIdentityAttribute.equals(BrsConst.OBJECT_IDENTITY_ATTRIBUTE_ID) ? e.getObjectId().toString()
                            : objectIdentityAttribute.equals(BrsConst.OBJECT_IDENTITY_ATTRIBUTE_MOBILE) ? objectIdentityAttributeValue
                            : objectIdentityAttribute.equals(BrsConst.OBJECT_IDENTITY_ATTRIBUTE_IP) ? objectIp : "";
                }
                recordVO.setObjectIdentity(objectIdentityText);
                recordVO.setObjectIdentityAttribute(objectIdentityAttributeText);
                recordVO.setChannelName(ObjectConvertUtil.toString(jsonObject.get("channelName")));
            }
            eventRecordVOList.add(recordVO);
        }
        return eventRecordVOList;
    }

}
